package com.societyGames.codeAlong.state.codeExercise.model
{
import com.societyGames.codeAlong.state.codeExercise.model.link.IHyperText;
import com.societyGames.codeAlong.state.codeExercise.model.link.ILinkable;

public class FunctionData implements ILinkable, IHyperText
{
  public var name:String;
  public var description:String;
  public var example:String;
  public var returnData:FunctionReturnData;
  public var parameters:Vector.<FunctionParameterData> = new Vector.<FunctionParameterData>();
  public var isGlobal:Boolean;

  private var _parent:ILinkable;

  //IHyperText-->
  public function toHyperText():String
  {
    //Display signature
    var text:String = "<b>" + name + "(";
    var parameterText:String = "";
    for each (var parameterData:FunctionParameterData in parameters)
    {
      if (parameterText.length > 0)
      {
        parameterText += ", ";
      }
      parameterText += parameterData.name + (parameterData.type.length > 0 ? ":" + parameterData.type : "");
      if (parameterData.defaultValue != null && parameterData.defaultValue.length > 0)
      {
        parameterText += "=" + parameterData.defaultValue;
      }
    }
    text += parameterText;
    //Display signature and description
    text += "):" + returnData.type + "</b><br>" + description + "<br>";
    //Parameters
    if (parameters.length > 0)
    {
      text += "<br><b>Parameters</b><br>";
      for each (parameterData in parameters)
      {
        text += parameterData.toHyperText() + "<br>";
      }
    }
    //Return
    text += "<br><b>Returns</b><br>";
    if (this.returnData.type != "void")
    {
      text += "<b>" + this.returnData.type + "</b> " + returnData.description + "<br>";
    }
    else
    {
      text += "Nothing.<br>";
    }
    //Example
    if (this.example != null && this.example.length > 0)
    {
      text += "<br><b>Example</b><br>" + this.example + "<br>";
    }
    return text;
  }

  //<--IHyperText

  //ILinkable-->
  public function toLink():String
  {
    return _parent.toLink() + LibraryData.separator + this.name;
  }

  //<--ILinkable

  public static function fromXml(parent:ILinkable, xml:XML):FunctionData
  {
    var functionData:FunctionData = new FunctionData();

    //Set parent
    functionData._parent = parent;

    //Get attributes
    functionData.name = xml.@name;
    functionData.description = xml.@description;
    functionData.isGlobal = xml.hasOwnProperty("@isGlobal") && xml.@isGlobal == "true";

    //Use accessor since return is a keyword.
    var returnXml:XML = xml["return"][0];
    //ReturnData.fromXml will return appropriate value on null.
    functionData.returnData = FunctionReturnData.fromXml(functionData, returnXml);

    //Handle arguments
    for each (var parameterXml:XML in xml.parameter)
    {
      functionData.parameters.push(FunctionParameterData.fromXml(functionData, parameterXml));
    }

    //Get the example if there is one.
    if ("example" in xml)
    {
      functionData.example = xml.example[0].toString();
    }

    //The newly created
    return functionData;
  }
}
}